<template>
  <div class="card-page" style="margin-bottom: 40px;">
    <tool-bar nav="" :title="action_name + 'Api定义'">
      <el-button size="small" @click="$router.push('/dev/api-define/add')" v-if="$props.action=='edit'">新建</el-button>
      <el-button size="small" @click="save_click" type="primary" v-if="!isView">保存</el-button>
    </tool-bar>
    <el-row :gutter="12" type="flex">
      <el-col :span="12">
        <el-card shadow="always">
          <kv label="名称">
            <el-input v-model="info.name" chk="*"/>
          </kv>
          <kv label="HTTP方法">
            <selector v-model="info.httpMethod" enum="HttpMethod" chk="*"/>
          </kv>
          <kv label="地址">
            <el-input v-model="info.url" @change="url_change" chk="*"/>
          </kv>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card shadow="always">
          <kv label="产品线">
            <product-line @change="(v,m)=>info.productLine.name=m.name" v-model="info.productLine.code"
                          chk="*"></product-line>
          </kv>
          <kv label="应用">
            <el-input v-model="info.app" chk="*"></el-input>
          </kv>
          <kv label="模块">
            <el-input v-model="info.group"/>
          </kv>
          <kv label="备注">
            <el-input v-model="info.remark" type="textarea"/>
          </kv>
        </el-card>
      </el-col>
    </el-row>
    <div id="dynamicElement">
      {{ info.url }}<br/>
      <span style="font-size:small">{{ info.name }}</span>
    </div>

    <el-card shadow="always" class="request-header" v-if="info?.requestUrlPathParameters?.length">
      <template #header>
        <div class="header">
          <span>请求路径参数</span>
        </div>
      </template>
      <api-array v-model="info.requestUrlPathParameters" is-root pin></api-array>
    </el-card>

    <el-card shadow="always" class="request-header" v-if="!isView || info?.requestUrlQueryParameters?.length">
      <template #header>
        <div class="header">
          <span>请求地址查询参数</span>

          <el-button
              @click="url_add_click()"
              text
              :icon="CirclePlus"
              title="添加子元素"></el-button>
        </div>
      </template>
      <api-array v-model="info.requestUrlQueryParameters" is-root ref="requestUrlQueryParameters"></api-array>
    </el-card>

    <el-card shadow="always" class="request-header" v-if="!isView || info?.requestHeaderParameters?.length">
      <template #header>
        <div class="header">
          <span>请求头参数</span>
          <el-button text
                     @click="header_add_click()"
                     :icon="CirclePlus"
                     title="添加子元素"></el-button>
        </div>
      </template>
      <api-array v-model="info.requestHeaderParameters" is-root ref="requestHeaderParameters"></api-array>
    </el-card>

    <!--    <el-card shadow="always" class="request-header" v-if="!isView || info?.uploadFileName">-->
    <!--      <template #header>-->
    <!--        <div class="header">-->
    <!--          <span>文件上传</span>-->
    <!--        </div>-->
    <!--      </template>-->

    <!--      <div>-->
    <!--        1. 要求 content-type:multipart/form-data <br/>-->
    <!--        2. 参数名: {{ info.uploadFileName }}-->
    <!--      </div>-->
    <!--    </el-card>-->

    <el-card shadow="always" class="request-header">
      <template #header>
        <div class="header">
          <span>请求体参数</span>
        </div>
      </template>
      <api-json v-model="info.requestBodyParameters" is-root
                v-if="!isView || info.requestBodyParameters?.items?.length"></api-json>
      <div v-else>无</div>
    </el-card>

    <el-card shadow="always" class="response-header" v-if="!isView || info?.responseHeaderParameters?.length">
      <template #header>
        <div class="header">
          <span>响应头参数</span>

          <el-button
              @click="response_header_add_click()"
              :icon="CirclePlus"
              text
              title="添加子元素"></el-button>

        </div>
      </template>
      <api-array v-model="info.responseHeaderParameters" ref="responseHeaderParameters"></api-array>
    </el-card>

    <el-card shadow="always" class="response-header">
      <template #header>
        <div class="header">
          <span>响应体参数</span>
        </div>
      </template>
      <api-json v-model="info.responseBodyParameters" is-root
                v-if="!isView || info.responseBodyParameters?.items?.length"></api-json>
      <div v-else>无</div>
    </el-card>
  </div>
</template>

<script setup>
/**
 * Created by CodeGenerator  at 2023-10-03 20:42:08
 */

import apiJson from "../../../component/api-json-parameter.vue";
import apiArray from "../../../component/api-array-parameter.vue";
import productLine from "@/component/product-line.vue";
import {Setting, CirclePlus, Remove, CaretBottom, CaretTop} from '@element-plus/icons-vue'


//定义 vue2的this,当前组件
const $self = getCurrentInstance();

//定义 $attrs
const $attrs = useAttrs();

//定义data
const $data = reactive({
  HttpMethod: jv.enum.HttpMethod.getData(),
  "info": {
    "productLine": {},
    "url": "",
    "httpMethod": "POST",
    "requestHeaderParameters": [],
    "requestBodyParameters": {},
    "requestUrlPathParameters": [],
    "requestUrlQueryParameters": [],
    "responseBodyParameters": {},
    "responseHeaderParameters": []
  }, "header": []
});
const info = $computed(() => $data.info);

const $props = defineProps({
  id: {type: String},
  action: {type: String}
});
const action_name = $computed(() => {
  return {add: "添加", edit: "修改", view: "查看"}[$props.action]
});

const isView = $props.action == "view";

const instance = getCurrentInstance()

const add_click = function () {
};
const url_change = function () {
  if (!info.url) {
    info.requestUrlPathParameters = [];
  }
  info.requestUrlPathParameters = info.url.getVarKeys().distinct().map(it => {
    var def = {key: it, type: "Text", stringType: "Normal"};
    return def;
  });
};

const setViewMode = function () {
  nextTick(() => {
    var i = 0;

    function findAllComponents(vnode, callback) {


      function traverse(vnode) {
        if (vnode.component) {
          // 是组件节点，记录它的组件实例
          if (callback(vnode.component) == false) {
            return;
          }
        } else {
          i++;
        }

        // 遍历直接子节点
        if (vnode.children && vnode.children.forEach) {
          vnode.children.forEach(child => {
            if (typeof child !== 'string' && child.type) {
              // 如果是组件或元素，继续遍历
              traverse(child)
            }
          })
        }

        // 如果是组件，还要递归遍历它的 subTree
        if (vnode.component) {
          traverse(vnode.component.subTree)
        }
      }

      traverse(vnode)
      return
    }

    var map = new Set();
    findAllComponents(instance.subTree, it => {
      var tag = it.type.name;
      if (!tag) {
        return;
      }
      map.add(tag);
      if (tag == "ElButton") {
        it.vnode.el.style.display = "none";
      }
      if (tag.IsIn("ElInput", "ElSelect", "ElSwitch", "selector")) {

        it.props.disabled = true;
        it.props.readOnly = true;
        if (tag == "ElInput") {
          Array.from(it.vnode.el.querySelectorAll("input")).forEach(item => {
            item.placeholder = "";
          })
        }

        if (tag == "selector") {
          return;
        }
        return false;
      }

    })

    console.log("tags: " + Array.from(map).join(","))
  })
}

const loadData = async function () {
  if (!$props.id) return;
  let res = await jv.$http.post("/dev/api-define/detail/" + $props.id)
  $data.info = res.data.data;


  if (isView) {
    setViewMode();
  }
};
const save_click = async function () {
//校验

  var h = {};
  $data.header.forEach(it => {
    h[it.key] = it.value;
  });
  var info2 = Object.assign({}, info, h);
  let res = await jv.$http.post("/dev/api-define/save", info2)
//[axios拦截器中已处理了异常]。
  jv.info(action_name + " 成功");
  let id = res.data.data || info2.id;
  if (!id) {
    return jv.error("找不到 id");
  }
};


const requestUrlQueryParameters = ref();
const url_add_click = () => {
  requestUrlQueryParameters.value.add_click();
}

const requestHeaderParameters = ref();
const header_add_click = () => {
  requestHeaderParameters.value.add_click();
}

const responseHeaderParameters = ref();
const response_header_add_click = () => {
  responseHeaderParameters.value.add_click();
}

const loadFixDiv = () => {

  const element = document.getElementById('dynamicElement');
  let lastScroll = 0;

  // 节流函数优化性能
  var card = document.querySelectorAll(".card-page")[0].parentElement;

  const handler = () => {
    const now = Date.now();
    if (now - lastScroll > 200) { // 每100ms检查一次

      if (card.scrollTop > 150) {
        element.classList.add("show")
      } else {
        element.classList.remove("show");
      }
      lastScroll = now;
    }
  }


  card.addEventListener('scroll', jv.debounce(handler, 200));
}

onMounted(() => {
  loadData();
  loadFixDiv();
})


</script>
<style scoped lang="scss">
#dynamicElement {
  position: fixed;
  right: 40px;
  top: 50px;
  background-color: rebeccapurple;
  color: white;
  padding: 10px;
  transition: opacity 0.3s;
  opacity: 0;
  max-width: 400px;
  z-index: 9999;
  border-radius: 10px;
}

#dynamicElement.show {
  opacity: 1;
}

.header {
  display: flex;
  flex-direction: row;
  align-items: center;

  button {
    color: white;
    font-size: 20px;
    padding: 0;
    width: 36px;
    height: 12px;
    display: flex;
    justify-content: center;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;

    &:hover {
      background-color: unset !important;
    }
  }

}

::v-deep(.el-card__header) {
  font-weight: bold;
  color: white;
  padding: 6px 10px;
  font-size: 16px;
}

.request-header ::v-deep(.el-card__header) {
  background-color: #668ef3;
}


.response-header ::v-deep(.el-card__header) {
  background-color: #249dbd;
}

::v-deep(.el-input.is-disabled), ::v-deep(.el-input.is-disabled *) {
  color: rgb(48, 48, 48) !important;
  -webkit-text-fill-color: rgb(48, 48, 48) !important;
  outline: none !important;
  box-shadow: none !important;
}
</style>